package cn.lovemmd.model.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.lovemmd.model.entity.Model;
import cn.lovemmd.model.entity.DownloadLog;
import cn.lovemmd.model.mapper.ModelMapper;
import cn.lovemmd.model.mapper.DownloadLogMapper;
import cn.lovemmd.model.service.ModelService;
import cn.lovemmd.model.util.JwtUtil;
import cn.lovemmd.model.util.RateLimitUtil;
import cn.lovemmd.model.vo.ModelVO;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 模型服务实现类 - 用户展示页面后台（只读）
 * 为了安全考虑，移除了所有增删改功能，只保留查询和统计功能
 * 
 * @author TLS
 * @since 2024-01-01
 */
@Service
@RequiredArgsConstructor
public class ModelServiceImpl extends ServiceImpl<ModelMapper, Model> implements ModelService {

    private static final Logger log = LoggerFactory.getLogger(ModelServiceImpl.class);
    private final DownloadLogMapper downloadLogMapper;
    private final JwtUtil jwtUtil;
    private final RateLimitUtil rateLimitUtil;

    @Override
    public List<ModelVO> getModelList(String search, String occupation) {
        // 构建查询条件
        LambdaQueryWrapper<Model> queryWrapper = new LambdaQueryWrapper<>();
        
        // 搜索条件
        if (StringUtils.hasText(search)) {
            queryWrapper.like(Model::getMName, search);
        }
        
        // 职业筛选
        if (StringUtils.hasText(occupation)) {
            queryWrapper.eq(Model::getMOccupation, occupation);
        }
        
        // 按创建时间倒序
        queryWrapper.orderByDesc(Model::getCreateTime);
        
        // 执行查询，返回所有数据
        List<Model> modelList = this.list(queryWrapper);
        
        // 转换为VO
        return modelList.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public ModelVO getModelById(Long id) {
        Model model = this.getById(id);
        return model != null ? convertToVO(model) : null;
    }



    @Override
    public Object getModelStats() {
        Map<String, Object> stats = new HashMap<>();
        
        // 总模型数
        long totalCount = this.count();
        stats.put("total", totalCount);
        
        // 各职业模型数量
        List<Map<String, Object>> occupationStats = new ArrayList<>();
        String[] occupations = {"bladePoint", "Flame", "doubleGun", "machineGun", "guidedMissile", "sniper", "medic", "grenade", "engineer"};
        String[] occupationNames = {"刀锋", "烈焰", "双枪", "机枪", "导弹", "狙击", "医生", "榴弹", "工程师"};
        
        for (int i = 0; i < occupations.length; i++) {
            long count = this.count(new LambdaQueryWrapper<Model>()
                    .eq(Model::getMOccupation, occupations[i]));
            
            Map<String, Object> occupationStat = new HashMap<>();
            occupationStat.put("occupation", occupations[i]);
            occupationStat.put("name", occupationNames[i]);
            occupationStat.put("count", count);
            occupationStats.add(occupationStat);
        }
        
        stats.put("occupationStats", occupationStats);
        
        return stats;
    }

    @Override
    public List<Object> getOccupationList() {
        List<Object> occupationList = new ArrayList<>();
        
        String[] occupations = {"bladePoint", "Flame", "doubleGun", "machineGun", "guidedMissile", "sniper", "medic", "grenade", "engineer"};
        String[] occupationNames = {"刀锋", "烈焰", "双枪", "机枪", "导弹", "狙击", "医生", "榴弹", "工程师"};
        
        for (int i = 0; i < occupations.length; i++) {
            Map<String, Object> occupation = new HashMap<>();
            occupation.put("value", occupations[i]);
            occupation.put("label", occupationNames[i]);
            occupationList.add(occupation);
        }
        
        return occupationList;
    }

    @Override
    public List<Model> selectByOccupation(String occupation) {
        return this.baseMapper.selectByOccupation(occupation);
    }

    @Override
    public List<Model> selectByCategory(String category) {
        return this.baseMapper.selectByCategory(category);
    }

    @Override
    public List<Model> searchByKeyword(String keyword) {
        return this.baseMapper.searchByKeyword(keyword);
    }

    @Override
    public List<Model> selectTopModels(int limit) {
        return this.baseMapper.selectTopModels(limit);
    }

    @Override
    public Long countTotalModels() {
        return this.baseMapper.countTotalModels();
    }

    @Override
    public List<Object> getOccupationStats() {
        return this.baseMapper.getOccupationStats();
    }

    @Override
    public List<Object> getCategoryStats() {
        return this.baseMapper.getCategoryStats();
    }

    @Override
    public void recordDownload(Long modelId, String username, String ip, String userAgent, String referer) {
        try {
            // 获取模型信息
            Model model = this.getById(modelId.intValue());
            if (model == null) {
                log.warn("模型不存在，modelId: {}", modelId);
                return;
            }

            // 创建下载日志
            DownloadLog downloadLog = DownloadLog.builder()
                    .modelId(modelId)
                    .userId(null) // 暂时设为null，后续可以根据username查找用户ID
                    .ip(ip)
                    .userAgent(userAgent)
                    .referer(referer)
                    .createdAt(LocalDateTime.now())
                    .build();

            // 保存下载日志
            downloadLogMapper.insert(downloadLog);

            log.info("记录下载成功，modelId: {}, username: {}", modelId, username);
        } catch (Exception e) {
            log.error("记录下载失败，modelId: {}, username: {}", modelId, username, e);
        }
    }

    @Override
    public void recordView(Long modelId, String username, String ip, String userAgent, String referer) {
        try {
            // 更新模型浏览次数
            this.baseMapper.incrementViewCount(modelId);
            log.info("记录访问成功，modelId: {}, username: {}", modelId, username);
        } catch (Exception e) {
            log.error("记录访问失败，modelId: {}, username: {}", modelId, username, e);
        }
    }

    /**
     * 生成下载token
     * 
     * @param modelId 模型ID
     * @param username 用户名
     * @param ip IP地址
     * @return 下载token
     */
    public String generateDownloadToken(Long modelId, String username, String ip) {
        // 检查速率限制
        if (!rateLimitUtil.tryConsume(ip)) {
            log.warn("IP {} 请求过于频繁", ip);
            throw new RuntimeException("请求过于频繁，请稍后再试");
        }
        
        // 验证模型是否存在
        Model model = this.getById(modelId.intValue());
        if (model == null) {
            log.warn("模型不存在，modelId: {}", modelId);
            throw new RuntimeException("模型不存在");
        }
        
        // 生成下载token
        String token = jwtUtil.generateDownloadToken(modelId, username, ip);
        log.info("生成下载token成功，modelId: {}, username: {}, ip: {}", modelId, username, ip);
        
        return token;
    }

    /**
     * 将Model实体转换为ModelVO
     */
    private ModelVO convertToVO(Model model) {
        ModelVO vo = new ModelVO();
        // 手动映射字段
        vo.setMId(model.getMId());
        vo.setMName(model.getMName());
        vo.setMOccupation(model.getMOccupation());
        vo.setMUrl(model.getMUrl());
        vo.setMImg(model.getMImg());
        // 新增字段映射
        vo.setMModelSource(model.getMModelSource());
        vo.setMBoneBinding(model.getMBoneBinding());
        vo.setMPhysicsBinding(model.getMPhysicsBinding());
        vo.setMExpressionMaking(model.getMExpressionMaking());
        vo.setCreateTime(model.getCreateTime());
        vo.setUpdateTime(model.getUpdateTime());
        return vo;
    }
}
